/**
 * gulp任务：
 * 编译输出scss文件 gulp-sass
 * 编译输出js文件 gulp-babel @babel/core @babel/preset-env
 * 拷贝public目录下文件和字体文件
 * 压缩输出图片文件 gulp-imagemin
 * 编译输出html文件 gulp-swig
 * 清理dist .tmp del
 * 启动一个服务器 browser-sync 
 * 监听文件改动，自动编译，刷新页面
 * 合并html中引用的资源 gulp-useref
 * 压缩css html js gulp-uglify gulp-htmlmin gulp-clean-css
*/

const { src, dest, parallel, series, watch } = require('gulp')

const del = require('del')
const browserSync = require('browser-sync')

const loadPlugins = require('gulp-load-plugins')
const autoprefixer = require('autoprefixer')

const plugins = loadPlugins()
const bs = browserSync.create()


let config = {
  build: {
    src: 'src',
    dest: 'release',
    temp: '.tmp',
    public: 'public',
    paths: {
      styles: 'assets/styles/*.scss',
      scripts: 'assets/scripts/*.js',
      pages: '*.html',
      images: 'assets/images/**',
      fonts: 'assets/fonts/**'
    }
  }
}
try {
  const loadConfig = require(`${cwd}/pages.config.js`)
  config = Object.assign({}, config, loadConfig)
} catch (e) { }

const { build } = config
const { paths } = build

const clean = () => {
  return del([build.dest, build.temp])
}

const style = () => {
  return src(paths.styles, { base: build.src, cwd: build.src })
    .pipe(plugins.sass({ outputStyle: 'expanded', sourceMap: true }))
    .pipe(plugins.postcss([
      autoprefixer(),
    ]))
    .pipe(dest(build.temp))
    .pipe(bs.reload({ stream: true }))
}

const script = () => {
  return src(paths.scripts, { base: build.src, cwd: build.src })
    .pipe(plugins.babel({ presets: ['@babel/preset-env'] }))
    .pipe(dest(build.temp))
    .pipe(bs.reload({ stream: true }))
}

const page = () => {
  return src(paths.pages, { base: build.src, cwd: build.src })
    .pipe(plugins.swig({ data: config.data, defaults: { cache: false } }))
    .pipe(dest(build.temp))
    .pipe(bs.reload({ stream: true }))
}

const image = () => {
  return src(paths.images, { base: build.src, cwd: build.src })
    .pipe(plugins.imagemin())
    .pipe(dest(build.dest))
}

const font = () => {
  return src(paths.fonts, { base: build.src, cwd: build.src })
    .pipe(plugins.imagemin())
    .pipe(dest(build.dest))
}

const extra = () => {
  return src('**', { base: build.public, cwd: build.public })
    .pipe(dest(build.dest))
}

const serve = () => {
  watch(paths.styles, { cwd: build.src }, style)
  watch(paths.scripts, { cwd: build.src }, script)
  watch(paths.pages, { cwd: build.src }, page)
  watch([
    paths.images,
    paths.fonts,
    build.public
  ], { cwd: build.src }, bs.reload)

  bs.init({
    notify: false,
    port: 2020,
    server: {
      baseDir: [build.temp, build.src, build.public],
      routes: {
        '/node_modules': 'node_modules'
      }
    }
  })
}

const useref = () => {
  return src(paths.pages, { base: build.temp, cwd: build.temp })
    .pipe(plugins.useref({ searchPath: [build.temp, '.'] }))
    .pipe(plugins.if(/\.js$/, plugins.uglify()))
    .pipe(plugins.if(/\.css$/, plugins.cleanCss()))
    .pipe(plugins.if(/\.html$/, plugins.htmlmin({
      collapseWhitespace: true,
      minifyCSS: true,
      minifyJS: true
    })))
    .pipe(dest(build.dest))
}

const compile = parallel(style, script, page)

const prod = series(
  clean,
  parallel(
    series(compile, useref),
    image,
    font,
    extra
  )
)

const develop = series(compile, serve)

module.exports = {
  clean,
  prod,
  develop
}
